org 7c00h

global _start

_start:

mov [drv], dl      ; Salvar o local de onde demos boot

; Setar modo de video para 03h
set_video:
	xor ax, ax
	mov ah, 0x00
	mov al, 0x03
	int 10h

; Configurar video
; ver http://www.osdever.net/FreeVGA/vga/vgareg.htm#indexed
; ver http://www.osdever.net/FreeVGA/vga/graphreg.htm#06

cli

call canSendCommand
call readKeyboardStatus
call canSendCommand
call writeNewStatus
call readKeyboardStatus
call loadKernelFromDisk


load_gdt:
	lgdt [GDT]

; Enable pmode
	xor eax, eax
	mov eax, cr0
	or  eax, 1
	mov cr0, eax
	jmp 0x08:ahead ; far jump to activate new code segment ;D

loadKernelFromDisk:

diskSetup:
	mov ax,0        ; Função para resetar o disco rígido
	mov dl,[drv]    ; O drive que vamos resetar
 
	int 13h         ; Chama a interrupção de disco
	jc diskSetup    ; Se der erro, tentamos de novo
 
diskRead:
	mov ah,02h    ; Função para ler o disco
	mov al,32     ; Ler setores
 
	mov ch,0      ; Apontar para o cilindro 0
	mov cl,0x02   ; Ler a partir do setor 2
 
	mov dh,0      ; Cabeça 0
	mov dl,[drv]  ; Disco de onde queremos ler os dados
 
; Os dados que lemos com essa função são armazenados em ES:BX
; No nosso caso aqui entao teremos 1000h:0
 
	mov bx, 0x1000
	mov es, bx
 
	xor bx, bx
 
	int 13h       ; Interrupção do disco
	jc diskRead   ; Em caso de erro, tenta de novo

writeNewStatus:
	xor  ax, ax
	mov  al, 0xD1
	out  0x64, al
	call canSendCommand     ; controladora ja consumiu o comando de que
	                        ; desejo escrever o novo status do teclado

	xor  ax, ax
	mov  al, [kbd]
	
	or  al, 2               ; ativa o bit do A20
	out  0x60, al
	ret
	

readKeyboardStatus:
	xor  ax, ax
	mov  al, 0xD0
	out  0x64, al
	mov cl, 0x41
	call canReadBuffer

	xor  ax, ax
	in   al, 0x60
	mov  [kbd], al
	
	ret

canSendCommand:
	xor  ax, ax
	in   al, 0x64
	and  al, 00000010b
	cmp  al, 00000010b
	je   canSendCommand
	ret

canReadBuffer:
	in   al, 0x64
	and  al, 0x01
	cmp  al, 0x01

	jne  canReadBuffer

	ret

bits 32
ahead:

	; Load data segments
	xor eax, eax
	xor ebx, ebx
	xor ecx, ecx
	xor edx, edx
	mov ax, 0x10
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax

	; Load stack segment
	xor ax, ax
	xor ebx, ebx
	
	mov ax, 0x10
	;mov ebx, 0x5000
	mov ss, ax
	;mov esp, ebx

	; Load TSS
	xor ax, ax
	mov ax, 0x0020
	ltr ax

	jmp 0x08:0x10000    ; jmp into the kernel

end:
	jmp end

GDT DW 39       ; GDT Size in bytes
	DW GilgaGDT

GilgaGDT DW 0x0000         ; null descriptor
		 DW 0x0000         ; null descriptor
		 DW 0x0000         ; null descriptor
		 DW 0x0000         ; null descriptor
		 
		 ;Code segment
		 DW 0xFFFF         ; segment limit 15:00
		 DW 0x0000         ; base address  15:00
		 DB 0x00           ; base address  23:16
		 ;DB 10011010b      ; P DPL 1 Type (Code segment)
		 DB 0x9A           ; P DPL 1 Type (Code segment)
		 DB 11011111b      ; G D 0 AVL Limit 19:16
		 DB 0x00           ; base address 31:23
		 
		 ; Data segment
		 DW 0xFFFF         ; segment limit 15:00
		 DW 0x0000         ; base address  15:00
		 DB 0x00           ; base address  23:16
		 DB 10010010b      ; P DPL 1 Type (Data segment)
		 DB 11011111b      ; G D 0 AVL Limit 19:16
		 DB 0x00           ; base address 31:23
		 
		 ; Stack segment
		 DW 0xFFFF         ; segment limit 15:00
		 DW 0x4000         ; base address  15:00
		 DB 0x00           ; base address  23:16
		 DB 10010110b      ; P DPL 1 Type (Stack segment)
		 DB 11011111b      ; G D 0 AVL Limit 19:16
		 DB 0x00           ; base address 31:23
		 
		 ;TSS
		 DW 0xFFFF         ; segment limit 15:00
		 DW 0x0000         ; base address  15:00
		 DB 0x00           ; base address  23:16
		 DB 10001001b      ; P DPL 1 Type (Code segment)
		 DB 11011111b      ; G D 0 AVL Limit 19:16
		 DB 0x00           ; base address 31:23

kbd: db 0x00
drv: db 0
kernel_size: db 1

times 512 - 2 - ($ - $$) db 0
DW 0xAA55
